const name = "[z-perf]";

const log = (...args: any) => {
  console.log(name, ...args);
};

const warn = (...args: any) => {
  console.warn(name, ...args);
};

const perfMap = new Map<string, number[]>();

/**
 * add one record
 */
export const record = (key: string) => {
  if (perfMap.has(key)) {
    const perf_now = performance.now();
    const records = perfMap.get(key)!;
    const tail = records.at(-1)!;
    records.push(perf_now);
    const diff = perf_now - tail;
    log(`record ${key} - after ${diff}ms`);
  } else {
    perfMap.set(key, [performance.now()]);
    log(`record ${key} - first time`);
  }
};

/**
 * get diff time between two records.
 * diff(key) --> from last two to the last one
 * diff(key, n) --> from n-1 to n
 */
export function diff(key: string): void;
export function diff(key: string, to: number): void;
export function diff(key: string, from: number, to?: number): void;
export function diff(key: string, from?: number, to?: number): void {
  if (perfMap.has(key)) {
    const records = perfMap.get(key)!;
    if (from == null && to == null) {
      from = records.length - 2;
      to = records.length - 1;
    } else if (from == null) {
      from = to! - 1;
    } else if (to == null) {
      to = from;
      from = to - 1;
    }
    const start = records[from];
    const end = records[to!];
    const diff = end - start;
    log(`diff ${key} from ${from} to ${to} - ${diff}ms)`);
  } else {
    warn(`no such key ${key}`);
  }
}

/**
 * get all records
 */
export const get = (key: string) => {
  return perfMap.get(key);
};

/**
 * clear records
 */
export const clear = (key: string | undefined) => {
  if (key) {
    perfMap.delete(key);
    return;
  }
  perfMap.clear();
};
